package com.yanzhenjie.andserver.sample.util;

import android.os.Build;
import android.util.Log;

import androidx.annotation.RequiresApi;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Calendar;
import java.util.Locale;

/**
 * Date    2020-05-09
 * Author  WestWang
 * shell命令工具类
 */
public class ShellUtil {

    /**
     * 读取有线网络MAC地址
     *
     * @return 网卡eth0 MAC地址
     */
    public static String readMacAddress() {
        ShellResult result = exec("cat /sys/class/net/eth0/address", false);
        if (result == null || result.code != 0) {
            return "";
        }
        return result.msg;
    }

    /**
     * 读取Wi-Fi网络MAC地址
     *
     * @return 网卡wlan0 MAC地址
     */
    public static String readMacWifiAddress() {
        ShellResult result = exec("cat /sys/class/net/wlan0/address", false);
        if (result == null || result.code != 0) {
            return "";
        }
        return result.msg;
    }

    /**
     * 读取设备序列号
     *
     * @return 序列号
     */
    public static String readSn() {
        ShellResult result = exec("getprop  ro.serialno", false);
        if (result == null || result.code != 0) {
            return "";
        }
        return result.msg;
    }

    /**
     * 读取设备版本号
     *
     * @return 版本号
     */
    static String readVersion() {
        return exec("getprop ro.build.version.release", false).msg;
    }

    /**
     * 执行端口转换操作
     *
     * @return 网卡eth0 MAC地址
     */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public static String execPortChange(int port) {
        ShellResult result = execSu("iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port " + port, false);
        if (result == null || result.code != 0) {
            return "";
        }
        return result.msg;
    }

    /**
     * 设置系统时间
     *
     * @param timeInMillis 毫秒
     */
    public static void updateSysTime(long timeInMillis) {
        Calendar calendar = Calendar.getInstance(Locale.getDefault());
        calendar.setTimeInMillis(timeInMillis);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DATE);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minutes = calendar.get(Calendar.MINUTE);
        int year = calendar.get(Calendar.YEAR);
        int seconds = calendar.get(Calendar.SECOND);
        StringBuilder sb = new StringBuilder();
        sb.append("date ");
        if (month < 10) {
            sb.append("0");
        }
        sb.append(month);
        if (day < 10) {
            sb.append("0");
        }
        sb.append(day);
        if (hour < 10) {
            sb.append("0");
        }
        sb.append(hour);
        if (minutes < 10) {
            sb.append("0");
        }
        sb.append(minutes);
        sb.append(year);
        sb.append(".");
        if (seconds < 10) {
            sb.append("0");
        }
        sb.append(seconds);
        sb.append(" set");
        String cmd = sb.toString();
        Log.e("Time", "cmd---> " + cmd);

        StringBuilder stringBuffer = new StringBuilder();
        DataOutputStream dos = null;
        DataInputStream dis = null;
        int code;
        try {
            Process p = Runtime.getRuntime().exec("su");
            dos = new DataOutputStream(p.getOutputStream());
            dos.writeBytes(cmd + "\n");
            dos.writeBytes("exit\n");
            dos.flush();
            code = p.waitFor();
            if (code == 0) {
                dis = new DataInputStream(p.getInputStream());
            } else {
                dis = new DataInputStream(p.getErrorStream());
            }
            String line;
            while ((line = dis.readLine()) != null) {
                stringBuffer.append("\n").append(line);
            }
        } catch (Exception e) {
            Log.e("Time", e.toString());
            code = -999;
        } finally {
            if (dos != null) {
                try {
                    dos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (dis != null) {
                try {
                    dis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        Log.e("Time", "code---> " + code);
        Log.e("Time", "Time set result---> " + stringBuffer.toString());
    }

    /**
     * 执行shell指令
     *
     * @param cmd String 指令内容
     * @return 执行结果
     */
    public static ShellResult exec(String cmd, boolean format) {
        DataOutputStream dos = null;
        BufferedReader reader = null;
        ShellResult shellResult = null;
        try {
            Process p = Runtime.getRuntime().exec(cmd);
            shellResult = new ShellResult();
            StringBuilder stringBuffer = new StringBuilder();
            dos = new DataOutputStream(p.getOutputStream());
            dos.writeBytes("\n");
            dos.flush();
            dos.writeBytes("exit\n");
            dos.writeBytes("sync\n");
            dos.flush();
            shellResult.code = p.waitFor();
            if (shellResult.code == 0) {
                reader = new BufferedReader(new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8));
            } else {
                reader = new BufferedReader(new InputStreamReader(p.getErrorStream(), StandardCharsets.UTF_8));
            }
            String line;
            while ((line = reader.readLine()) != null) {
                if (format) {
                    stringBuffer.append("\n");
                }
                stringBuffer.append(line);
            }
            shellResult.msg = stringBuffer.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (dos != null) {
                try {
                    dos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return shellResult;
    }

    /**
     * 执行shell指令
     *
     * @param cmd String 指令内容
     * @return 执行结果
     */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public static ShellResult execSu(String cmd, boolean format) {
        DataOutputStream dos = null;
        BufferedReader reader = null;
        ShellResult shellResult = null;
        try {
            Process p = Runtime.getRuntime().exec("su");
            shellResult = new ShellResult();
            StringBuilder stringBuffer = new StringBuilder();
            dos = new DataOutputStream(p.getOutputStream());
            dos.writeBytes(cmd + "\n");
            dos.flush();
            dos.writeBytes("exit\n");
            dos.writeBytes("sync\n");
            dos.flush();
            shellResult.code = p.waitFor();
            if (shellResult.code == 0) {
                reader = new BufferedReader(new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8));
            } else {
                reader = new BufferedReader(new InputStreamReader(p.getErrorStream(), StandardCharsets.UTF_8));
            }
            String line;
            while ((line = reader.readLine()) != null) {
                if (format) {
                    stringBuffer.append("\n");
                }
                stringBuffer.append(line);
            }
            shellResult.msg = stringBuffer.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (dos != null) {
                try {
                    dos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return shellResult;
    }

    /**
     * shell指令返回结果
     */
    public static class ShellResult {
        public int code;
        public String msg;

        public ShellResult() {
        }
    }

}